import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
from docutils.nodes import label

carrier_image = None
secret_image = None

def plus(value):
    return bin(value)[2:].zfill(8)

def getCode(img):
    code = ""
    for i in range(img.size[0]):
        for j in range(img.size[1]):
            gray_value = img.getpixel((i, j))
            code += plus(gray_value)  # 使用 gray_value，无需将其转换为整数

    return code

def encry(img, code):
    count = 0
    codeLen = len(code)
    for i in range(img.size[0]):
        for j in range(img.size[1]):
            gray_value = img.getpixel((i, j))  # 提取元组中的灰度值
            if count == codeLen:
                break
            new_gray_value = (gray_value - gray_value % 2) + int(code[count])
            count += 1
            if count == codeLen:
                img.putpixel((i, j), new_gray_value)
                break
            img.putpixel((i, j), new_gray_value)
    return img

def deEncry(img, length):
    width = img.size[0]
    height = img.size[1]
    count = 0
    wt = ""
    for i in range(width):
        for j in range(height):
            gray_value = img.getpixel((i, j))  # 提取元组中的整数灰度值
            wt = wt + str(gray_value % 2)
            count += 1
            if count == length:
                break
        if count == length:
            break
    return wt

def showImage(wt, img_width, img_height):
    str1 = []
    for i in range(0, len(wt), 8):
        # 以每8位为一组二进制，转换为十进制
        str1.append(int(wt[i:i + 8], 2))

    # 图片大于水印图片1个像素，便于对比
    img_out = Image.new("L", (img_width, img_height))  # 使用灰度模式
    flag = 0
    for m in range(0, img_width):
        for n in range(0, img_height):
            if flag == len(str1):
                break
            img_out.putpixel((m, n), str1[flag])
            flag += 1
        if flag == len(str1):
            break
    return img_out

def select_image(label, is_carrier):
    global carrier_image, secret_image
    file_path = filedialog.askopenfilename(filetypes=[("Image files", "*.png *.jpg *.jpeg *.gif *.bmp")])
    if file_path:
        image = Image.open(file_path)
        image = image.resize((image.width // 4, image.height // 4), Image.LANCZOS)
        photo = ImageTk.PhotoImage(image)
        label.config(image=photo)
        label.image = photo
        # 根据 is_carrier 参数选择存储载体图像或秘密图像
        if is_carrier:
            carrier_image = image
        else:
            secret_image = image
def embed_watermark_endpoint(embedded_image_label):
    global carrier_image, secret_image, gray_img1
    if carrier_image is not None and secret_image is not None:
        # 将载体图像和秘密图像转换为灰度模式
        gray_img1 = carrier_image.convert('L')
        gray_img2 = secret_image.convert('L')
        secret_code = getCode(gray_img2)
        encry(gray_img1, secret_code)
        # 更新嵌入后的图像标签
        embedded_image_label.photo = ImageTk.PhotoImage(gray_img1)
        embedded_image_label.config(image=embedded_image_label.photo)
        # # 保存嵌入后的图像
        # gray_img1.save("embedded_image1.png")

def extract_watermark_endpoint(extracted_image_label):
    global secret_image, gray_img1
    if secret_image is not None:
        image_width = secret_image.size[0]
        image_height = secret_image.size[1]
        length = image_width * image_height * 8
        gray_img1 = gray_img1.convert('L')  # 使用灰度模式
        wt = deEncry(gray_img1, length)
        showImage(wt, image_width, image_height)
        image = showImage(wt, image_width, image_height)
        extracted_image_label.photo = ImageTk.PhotoImage(image)
        extracted_image_label.config(image=extracted_image_label.photo)

def resize_widgets(event):
    label.config(text=f"Width: {event.width}, Height: {event.height}")

# 创建主窗口
root = tk.Tk()
root.title("LSB数字水印系统")
root.geometry("300x300")  # 设置默认窗口大小

label = tk.Label(root)
label.grid(row=0, column=0, sticky="nsew")


system_label = tk.Label(root, text="LSB数字水印系统", font=("Helvetica", 16))
system_label.grid(row=0, column=0, columnspan=3, pady=10)  # Adjust row, column, columnspan, and pady as needed



label.grid(row=0, column=0, sticky="nsew")
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)

# 创建按钮和标签，使用grid布局
carrier_button = tk.Button(root, text="选择载体图像", command=lambda: select_image(carrier_image_label, True), width=5, height=2)
secret_button = tk.Button(root, text="选择水印图像", command=lambda: select_image(secret_image_label, False), width=10, height=2)
embed_button = tk.Button(root, text="嵌入水印", command=lambda: embed_watermark_endpoint(embedded_image_label), width=10, height=2)
extract_button = tk.Button(root, text="提取水印", command=lambda:extract_watermark_endpoint(extracted_image_label), width=10, height=2)

carrier_label = tk.Label(root, text="载体图像");
secret_label = tk.Label(root, text="水印图像");
embedded_label = tk.Label(root, text="载密图像");
extracted_label = tk.Label(root, text="水印图像");

carrier_image_label = tk.Label(root);
secret_image_label = tk.Label(root);
embedded_image_label = tk.Label(root);
extracted_image_label = tk.Label(root);

# 安排显示图像的区域
carrier_button.grid(row=1, column=0, padx=10, pady=0, sticky="nsew")
secret_button.grid(row=2, column=0, padx=10, pady=10,sticky="nsew")
embed_button.grid(row=3, column=0, padx=10, pady=10, sticky="nsew")
extract_button.grid(row=4, column=0, padx=10, pady=10, sticky="nsew")

carrier_label.grid(row=1, column=1, padx=10, pady=0, sticky="nsew")
secret_label.grid(row=2, column=1, padx=10, pady=10, sticky="nsew")
embedded_label.grid(row=3, column=1, padx=10, pady=10, sticky="nsew")
extracted_label.grid(row=4, column=1, padx=10, pady=10, sticky="nsew")

carrier_image_label.grid(row=1, column=2,sticky="nsew");
secret_image_label.grid(row=2, column=2, sticky="nsew");
embedded_image_label.grid(row=3, column=2, sticky="nsew");
extracted_image_label.grid(row=4, column=2, sticky="nsew");

root.bind("<Configure>", resize_widgets)
# 运行应用程序的主事件循环
root.mainloop()